require.config({
    paths: {
        'jquery': "../addons/fastflow/plugins/jquery/jquery.min",
        'toastr': "../addons/fastflow/plugins/toastr/taostr.min",
        'bootstrap-colorpicker': "../addons/fastflow/plugins/colorpicker/bootstrap-colorpicker.min",
        'x6': "../addons/fastflow/plugins/x6/x6",
    },
    shim: {
        'bootstrap-colorpicker': ['css!../addons/fastflow/plugins/colorpicker/bootstrap-colorpicker.min.css'],
    },
});
define(['jquery', 'x6', 'toastr', 'bootstrap-colorpicker'], function ($, X6, toastr, undefined) {
    var fastflow = {
        graph: null,
        startexist: false,
        endexist: false,
        selectedNode: null,
        flowId: null,
        saveAction: 'saveGraph',
        run: function (data, flowid, config = null) {
            fastflow.flowId = flowid;
            if (config != null) {
                config.nodeClick ? fastflow.nodeClick = config.nodeClick : null;
                config.blankClick ? fastflow.blankClick = config.blankClick : null;
                config.saveAction ? fastflow.saveAction = config.saveAction : null;
            }
            fastflow.initGraph();
            fastflow.initStencil();
            fastflow.initEvents();
            fastflow.initToolbarEvnet();
            fastflow.initData(data);
        },
        view: function (data) {
            fastflow.initGraph();
            fastflow.initData(data);
            fastflow.graph.drawBackground({color: '#ffffff'});
            fastflow.graph.clearGrid();
        },
        initGraph: function () {
            fastflow.graph = new X6.Graph({
                container: document.getElementById('container'),
                width: 6000,
                height: 6000,
                snapline: true,
                history: {
                    enabled: true,
                    ignoreChange: true,
                },
                selecting: {
                    enabled: true,
                    multiple: true,
                    rubberband: true,
                    movable: true,
                    showNodeSelectionBox: true,
                },
                mousewheel: {
                    enabled: true,
                    modifiers: ['ctrl', 'meta'],
                },
                connecting: {
                    allowBlank: false,
                    allowMulti: false,
                    allowLoop: false,
                    allowPort: false,
                    allowEdge: false,
                    snap: true,
                    highlight: true,
                    createEdge() {
                        return fastflow.graph.createEdge({
                            attrs: {
                                line: {
                                    stroke: 'orange',
                                    sourceMarker: 'path',
                                },
                            },
                        });
                    },
                    validateConnection({edge, edgeView, sourceView, targetView, sourcePort, targetPort, sourceMagnet, targetMagnet, sourceCell, targetCell, type}) {
                        if (targetCell.data['type'] == 'start') {
                            return false;
                        }
                        return true;
                    },
                },
                background: {
                    color: '#f8f7f7',
                },
                grid: {
                    size: 10,
                    visible: true,
                    args: {
                        color: '#68a3ff', 
                        thickness: 1,     
                    },
                },
                highlighting: {
                    magnetAvailable: {
                        name: 'stroke',
                        args: {
                            padding: 4,
                            attrs: {
                                'stroke-width': 2,
                                stroke: '#12bf18',
                            }
                        },
                    },
                },
            });
        },
        initEvents: function () {
            fastflow.graph.on('cell:mouseenter', ({cell}) => {
                if (cell.isNode()) {
                    if (cell.shape == 'polygon') {
                        offset = {x: 20, y: 20}
                    } else {
                        offset = {x: 10, y: 10}
                    }
                    cell.addTools([
                        {
                            name: 'button-remove',
                            args: {
                                x: 0,
                                y: 0,
                                offset: offset,
                            },
                        },
                    ]);
                    $('[data-cell-id=' + cell.id + '] .x6-port-body').css('visibility', 'visible');
                } else {
                    cell.addTools(['button-remove', 'vertices', 'segments']);
                }
            });
            fastflow.graph.on('cell:mouseleave', ({cell}) => {
                cell.removeTools();
                $('[data-cell-id=' + cell.id + '] .x6-port-body').css('visibility', 'hidden');
            });
            fastflow.graph.on('node:click', ({e, x, y, node, view}) => {
                if (node != fastflow.selectedNode){
                    fastflow.settingSubmit();
                }
                fastflow.expandAttributeblank();
                fastflow.reset();
                fastflow.selectedNode = node;
                fastflow.nodeClick(node);
            });
            fastflow.graph.on('blank:click', () => {
                if (fastflow.selectedNode != null){
                    fastflow.settingSubmit();
                }
                fastflow.collapseAttributeblank();
                fastflow.reset();
                fastflow.selectedNode = null;
                fastflow.blankClick();
            });
            fastflow.graph.on('node:removed', ({node, index, options}) => {
            });
            fastflow.graph.on('node:move',()=>{
                fastflow.collapseAttributeblank();
            });
            $('#btn-set').on('click', function () {
                fastflow.settingSubmit();
            });
            $('#body-colorpicker,#stroke-colorpicker,#label-colorpicker').colorpicker();
            $('#body-colorpicker input').on('input propertychange', function (event) {
                if (fastflow.selectedNode != null) {
                    fastflow.selectedNode.setAttrs({body: {fill: $(this).val()}});
                }
            });
            $('#stroke-colorpicker input').on('input propertychange', function (event) {
                if (fastflow.selectedNode != null) {
                    fastflow.selectedNode.setAttrs({body: {stroke: $(this).val()}});
                }
            });
            $('#label-colorpicker input').on('input propertychange', function (event) {
                if (fastflow.selectedNode != null) {
                    fastflow.selectedNode.setAttrs({label: {fill: $(this).val()}});
                }
            });
            $('#node-strokeWidth').on('input propertychange', function (event) {
                if (fastflow.selectedNode != null) {
                    fastflow.selectedNode.setAttrs({body: {strokeWidth: $(this).val()}});
                }
            });
            $('#node-width,#node-height').on('input propertychange', function (event) {
                if (fastflow.selectedNode != null) {
                    fastflow.selectedNode.resize($('#node-width').val(), $('#node-height').val());
                }
            });
            $('.colorpicker').on('click', function () {
                $('#body-colorpicker input,#stroke-colorpicker input,#label-colorpicker input').trigger('propertychange');
            });
            $('input:radio[name="row[flowoutmode]"]').on('click', function () {
                let val = $('input:radio[name="row[flowoutmode]"]:checked').val();
                if (val == '1') {
                    $('#flowoutcondition').addClass('hidden');
                } else if (val == '2') {
                    $('#flowoutcondition').removeClass('hidden');
                }
            });
            $('.leftblank').on('click',function () {
                if (fastflow.selectedNode != null){
                    fastflow.settingSubmit();
                }
                fastflow.collapseAttributeblank();
            })
            $('#c-scope').change(function () {
                if ($(this).val() == '5' || $(this).val() == '6') {
                    $('#worker').addClass('hidden');
                    $('#mode-select').addClass('hidden');
                } else {
                    $('#worker').removeClass('hidden');
                    $('#c-worker').selectPageClear();
                    $('#mode-select').removeClass('hidden');
                }
            });
            $('input[name="row[name]"]').on('input propertychange',function (event) {
                fastflow.settingSubmit();
            });

        },
        initStencil: function () {
            let stencil = new X6.Addon.Stencil({
                title: '',
                target: fastflow.graph,
                stencilGraphWidth: 200,
                stencilGraphHeight: '100%',
                layout: {
                    columns: 1,
                    columnWidth: 200,
                    rowHeight: 80,
                },
                groups: [
                    {
                        name: 'group1',
                        title: '流程组件',
                        collapsable: false,
                        graphHeight: 600,
                    },
                ],
                validateNode(droppingNode, options) {
                    if (droppingNode.data.type == 'start') {
                        let searchResult = fastflow.helper.searchNodeByType('start');
                        if (searchResult.length > 0) {
                            toastr.error('开始节点已存在');
                            return false;
                        }
                    } else if (droppingNode.data.type == 'end') {
                        let searchResult = fastflow.helper.searchNodeByType('end');
                        if (searchResult.length > 0) {
                            toastr.error('结束节点已存在');
                            return false;
                        }
                    }
                },
            });
            $('#module').append(stencil.container);
            let portcircle = {
                r: 4,
                magnet: true,
                stroke: '#8d8d8d',
                strokeWidth: 2,
                fill: '#fdff00',
                style: {
                    visibility: 'hidden',
                },
            };
            let outports = {
                groups: {
                    outtop: {
                        id: 'outtop',
                        position: 'top',
                        attrs: {
                            circle: portcircle,
                        },
                    },
                    outbottom: {
                        id: 'outbottom',
                        position: 'bottom',
                        attrs: {
                            circle: portcircle,
                        },
                    },
                    outleft: {
                        id: 'outleft',
                        position: 'left',
                        attrs: {
                            circle: portcircle,
                        },
                    },
                    outright: {
                        id: 'outright',
                        position: 'right',
                        attrs: {
                            circle: portcircle,
                        },
                    },
                },
                items: [
                    {
                        id: 'outtop',
                        group: 'outtop',
                    },
                    {
                        id: 'outbottom',
                        group: 'outbottom',
                    },
                    {
                        id: 'outleft',
                        group: 'outleft',
                    },
                    {
                        id: 'outright',
                        group: 'outright',
                    },
                ],
            };
            let start = new X6.Shape.Circle({
                x: 70,
                y: 40,
                width: 60,
                height: 60,
                attrs: {
                    body: {fill: '#88f299', strokeWidth: 1, stroke: '#347527'},
                    label: {text: '开始', fill: '#2a7a22'},
                },
                ports: outports,
                data: {
                    name: '开始',
                    type: 'start',
                },
            });

            let step = new X6.Shape.Rect({
                x: 40,
                y: 140,
                width: 120,
                height: 40,
                markup: [
                    {
                        tagName: 'rect',
                        selector: 'body',
                    },
                    {
                        tagName: 'image',
                        selector: 'img',
                    },
                    {
                        tagName: 'text',
                        selector: 'label',
                    },
                ],
                attrs: {
                    body: {rx: 3, ry: 3, fill: '#c7d9fc', stroke: '#5f95ff', strokeWidth: 1},
                    img: {
                        x: 6,
                        y: 6,
                        width: 16,
                        height: 16,
                        'xlink:href':
                            '/assets/addons/fastflow/img/avatar.png',
                    },
                    label: {text: '步骤', fill: '#262626'},

                },
                ports: outports,
                data: {
                    name: '步骤',
                    type: 'step',
                    sign: 1,
                    back: 1,
                    checkmode: 1,
                    scope: 1,
                    worker: '',
                },
            });

            let condition = new X6.Shape.Polygon({
                shape: 'polygon',
                x: 50,
                y: 220,
                width: 100,
                height: 70,
                points: '0,10 10,0 20,10 10,20',
                attrs: {
                    body: {
                        fill: '#efdbff',
                        stroke: '#9254de',
                        strokeWidth: 1
                    },
                    label: {text: '条件', fill: '#6e3210'},
                },
                ports: outports,
                data: {
                    name: '条件',
                    type: 'condition',
                    flowoutcondition: '[{"column":"","operator":"","value":"","step":""}]',
                },
            });

            let end = new X6.Shape.Circle({
                x: 70,
                y: 330,
                width: 60,
                height: 60,
                attrs: {
                    body: {fill: '#fa4e48', strokeWidth: 1, stroke: '#8f2424'},
                    label: {text: '结束', fill: '#ffffff'},
                },
                data: {
                    name: '结束',
                    type: 'end',
                },
            });

            var shapes = new Array(start.clone(), end.clone(), step.clone(), condition.clone());

            stencil.load(shapes, 'group1');
        },
        initData: function (data) {
            fastflow.graph.fromJSON(data);
        },
        initToolbarEvnet: function () {
            $('#toolabar-clear').on('click', function () {
                fastflow.toolbar.clear();
            })
            $('#toolabar-undo').on('click', function () {
                fastflow.toolbar.history.undo();
            })
            $('#toolabar-redo').on('click', function () {
                fastflow.toolbar.history.redo();
            })
            $('#toolabar-remove').on('click', function () {
                fastflow.toolbar.remove();
            })
            $('#toolabar-exporttopng').on('click', function () {
                fastflow.toolbar.export.toPNG();
            })
            $('#toolabar-exporttosvg').on('click', function () {
                fastflow.toolbar.export.toSVG();
            })
            $('#toolabar-check').on('click', function () {
                if (fastflow.selectedNode != null){
                    fastflow.settingSubmit();
                }
                fastflow.toolbar.check();
            })
            $('#toolabar-save').on('click', function () {
                if (fastflow.selectedNode != null){
                    fastflow.settingSubmit();
                }
                fastflow.toolbar.save();
            })
        },
        reset: function () {
            const nodes = fastflow.graph.getNodes();
            nodes.forEach((node) => {
                node.removeTools();
            })
        },
        settingSubmit: function () {
            if (!fastflow.selectedNode) {
                return;
            }
            if (fastflow.graph.hasCell(fastflow.selectedNode)) {
                fastflow.selectedNode.setAttrs({label: {text: $('input[name="row[name]"]').val()}}).data['name'] = $('input[name="row[name]"]').val();
                fastflow.selectedNode.setAttrs({body: {fill: $('#body-colorpicker input').val()}});
                fastflow.selectedNode.setAttrs({body: {stroke: $('#stroke-colorpicker input').val()}});
                if (fastflow.selectedNode.data.type == 'step') {
                    fastflow.selectedNode.data['sign'] = $('input[name="row[sign]"]:checked').val();
                    fastflow.selectedNode.data['back'] = $('input[name="row[back]"]:checked').val();
                    fastflow.selectedNode.data['scope'] = $('[name="row[scope]"]').val();
                    fastflow.selectedNode.data['worker'] = $('[name="row[worker]"]').val();
                    fastflow.selectedNode.data['checkmode'] = $('input[name="row[checkmode]"]:checked').val();
                } else if (fastflow.selectedNode.data.type == 'condition') {
                    fastflow.selectedNode.data['flowoutcondition'] = $('[name="row[flowoutcondition]"]').val();
                    let flowout = $.parseJSON(fastflow.selectedNode.data['flowoutcondition']);
                }
            }
        },
        toolbar: {
            history: {
                redo: function () {
                    fastflow.graph.redo();
                },
                undo: function () {
                    fastflow.graph.undo();
                }
            },
            export: {
                toPNG: function () {
                    fastflow.graph.toPNG(
                        (datauri) => {
                            X6.DataUri.downloadDataUri(datauri, 'chart.png');
                        },
                        {
                            copyStyles: false,
                            quality: 1,
                            padding: 100,
                        }
                    )
                },
                toSVG: function () {
                    fastflow.graph.toSVG((dataUri) => {
                            X6.DataUri.downloadDataUri(X6.DataUri.svgToDataUrl(dataUri), 'chart.svg');
                        },
                        {
                            copyStyles: false,
                        }
                    )
                }
            },
            remove: function () {
                let cells = fastflow.graph.getSelectedCells();
                cells.forEach(function (cell) {
                    cell.remove();
                })
            },
            save: function () {
                if (!fastflow.toolbar.check()) {
                    return;
                }
                fastflow.graph.toPNG(
                    (datauri) => {
                        $.ajax({
                            type: "POST",
                            url: fastflow.saveAction,
                            data: {flowid: fastflow.flowId, graph: fastflow.graph.toJSON(), image: datauri},
                            dataType: "json",
                            success: function (data) {
                                if (data['code'] == 1) {
                                    parent.Toastr.success(data['msg']);
                                    let index = parent.Layer.getFrameIndex(window.name);
                                    parent.Layer.close(index);
                                } else if (data['code'] == 0) {
                                    Toastr.error(data['msg']);
                                }
                            }
                        });
                    },
                    {
                        copyStyles: false,
                        quality: 1,
                        padding: 100,
                    }
                )

            },
            clear: function () {
                let cells = fastflow.graph.getCells();
                layer.confirm('确定清空画布吗？', {
                    skin: 'layui-layer-molv',
                    btn: ['确定', '取消'] 
                }, function () {
                    fastflow.graph.clearCells(cells);
                    layer.msg('操作成功');
                }, function () {
                });
            },
            check: function () {
                let msg = '';
                let flag = true;
                let startNode = null;
                let endNode = null;
                let startFlag = false;
                let endFlag = false;
                
                if (fastflow.graph.getCellCount() == 0) {
                    toastr.error('画布为空');
                    return false;
                }
                
                let nodes = fastflow.graph.getRootNodes();
                nodes.forEach(function (node) {
                    if (node.data.type != 'start') {
                        msg = '存在没有输入的节点';
                        flag = false;
                    } else {
                        startNode = node;
                        startFlag = true;
                    }
                })
                if (!startFlag) {
                    toastr.error('没有开始节点');
                    return false;
                }
                
                nodes = fastflow.graph.getLeafNodes();
                nodes.forEach(function (node) {
                    if (node.data.type != 'end') {
                        msg = '存在没有输出的节点';
                        flag = false;
                    } else {
                        endNode = node;
                        endFlag = true;
                    }
                })
                if (!endFlag) {
                    toastr.error('没有结束节点');
                    return false;
                }
                
                let neighbors = fastflow.graph.getNeighbors(startNode);
                let endIsNeighbor = false;
                neighbors.forEach(function (neighbor) {
                    if (neighbor.data.type == 'end') {
                        endIsNeighbor = true;
                    }
                })
                if (endIsNeighbor) {
                    toastr.error('开始节点不能与结束节点直接相连');
                    return false;
                }
                let steps = fastflow.helper.searchNodeByType('step');
                steps.forEach(function (node) {
                    if(node.data.scope != 5 && node.data.scope != 6 && node.data.worker == ''){
                        flag = false;
                        msg = '步骤“' + node.data.name + '”办理人员不能为空';
                    }
                })
                let conditions = fastflow.helper.searchNodeByType('condition');
                conditions.forEach(function (node) {
                    let flowout = $.parseJSON(node.data.flowoutcondition);
                    if (flowout.length < 2){
                        flag = false;
                        msg = '条件“' + node.data.name + '”必须包含至少2条转出路线，点击“追加”按钮新增转出路线';
                    }
                    else {
                        flowout.forEach(function (out) {
                            if(out.column == '' || out.operator == '' || out.value == '' || out.step == ''){
                                flag = false;
                                msg = '条件“' + node.data.name + '”参数设置不完整';
                            }
                        })
                    }
                })
                if (!flag) {
                    toastr.error(msg);
                    return false;
                }

                toastr.success('检查通过');
                return true
            },
        },
        helper: {
            searchNodeByType: function (type) {
                let nodes = fastflow.graph.getNodes();
                let result = [];
                for (let i = 0; i < nodes.length; i++) {
                    if (nodes[i].data.type == type) {
                        result.push(nodes[i]);
                    }
                }
                return result;
            }
        },
        startEndClick: function (node) {
            $('#flowset').addClass('hidden');
            $('#tab_flowset').addClass('hidden');
            $('#conditionset').addClass('hidden');
            $('#tab_conditionset').addClass('hidden');
        },
        conditionClick: function (node) {
            $('#flowset').addClass('hidden');
            $('#tab_flowset').addClass('hidden');
            $('#conditionset').removeClass('hidden');
            $('#tab_conditionset').removeClass('hidden');

            $('textarea[name="row[flowoutcondition]"]').val(node.data.flowoutcondition);
            $('textarea[name="row[flowoutcondition]"]').trigger("fa.event.refreshfieldlist");
            
            let outNodes = fastflow.graph.getNeighbors(node, options = {outgoing: true});
            
            $('#flownone').addClass('hidden');
            if (outNodes.length > 1) {
                $('#flowout').removeClass('hidden');
                $('#flownone').addClass('hidden');
                $('.step-select option').remove();
                outNodes.forEach(function (outNode) {
                    $('.step-select').append('<option value="' + outNode.id + '">' + outNode.getAttrs().label.text + '</option>');
                });
                $('.step-select').each(function () {
                    if ($(this).attr('data-value') != '') {
                        $(this).find('option[value=' + $(this).attr('data-value') + ']').attr('selected', '');
                    } else {
                        $(this).trigger('change');
                    }
                });
            } else {
                $('#flowout').addClass('hidden');
                $('#flownone').removeClass('hidden');
            }
            
        },
        stepClick: function (node) {
            $('#conditionset').addClass('hidden');
            $('#tab_conditionset').addClass('hidden');
            $('#flowset').removeClass('hidden');
            $('#tab_flowset').removeClass('hidden');
            node.data.sign == '0' ? $('#sign-switch0').trigger('click') : $('#sign-switch1').trigger('click');
            node.data.back == '0' ? $('#back-switch0').trigger('click') : $('#back-switch1').trigger('click');
            node.data.checkmode == '1' ? $('#checkmode1').trigger('click') : $('#checkmode2').trigger('click');
            node.data.scope == '5' || node.data.scope == '6' ? ($('#worker').addClass('hidden'), $('#mode-select').addClass('hidden')) : ($('#worker').removeClass('hidden'), $('#mode-select').removeClass('hidden'));
            $('#c-scope').val(node.data.scope !==null ? node.data.scope : 1);
            $('.selectpage').selectPageClear();
            $('#c-worker').val(node.data.worker !==null ? node.data.worker : '');
            $('.selectpage').selectPageRefresh();
        },
        nodeClick: function (node) {
            $('#btn-set').removeClass('disabled');
            $('#c-name').removeAttr('disabled');
            $('#c-name').val(node.getAttrs().label.text);
            $('#c-id').val(node.id);
            $('#a-attribute').trigger('click');
            $('#c-type').val(node.data.type == 'start' ? '开始' : node.data.type == 'step' ? '步骤' : node.data.type == 'condition' ? '条件' : node.data.type == 'end' ? '结束' : '未知');
            $('#body-colorpicker input,#stroke-colorpicker input,#label-colorpicker input,#node-strokeWidth,#node-width,#node-height').removeAttr('disabled');
            $('#body-colorpicker input').val(fastflow.selectedNode.getAttrs().body.fill).trigger('change');
            $('#stroke-colorpicker input').val(fastflow.selectedNode.getAttrs().body.stroke).trigger('change');
            $('#label-colorpicker input').val(fastflow.selectedNode.getAttrs().label.fill).trigger('change');
            $('#node-strokeWidth').val(fastflow.selectedNode.getAttrs().body.strokeWidth);
            $('#node-width').val(fastflow.selectedNode.size().width);
            $('#node-height').val(fastflow.selectedNode.size().height);
            $('[data-cell-id=' + node.id + '] .x6-port-body').css('visibility', 'hidden');

            if (node.data.type == 'start' || node.data.type == 'end') {
                fastflow.startEndClick(node);
            } else if (node.data.type == 'condition') {
                fastflow.conditionClick(node);
            } else if (node.data.type == 'step') {
                fastflow.stepClick(node);
            }
        },
        blankClick: function () {
            $('#a-attribute').trigger('click');
            $('#btn-set').addClass('disabled');
            $('#c-name').attr('disabled', '').val('');
            $('#c-id').val('');
            $('#c-type').val('');
            $('#flowset').addClass('hidden');
            $('#tab_flowset').addClass('hidden');
            $('#conditionset').addClass('hidden');
            $('#tab_conditionset').addClass('hidden');
            $('#body-colorpicker input,#stroke-colorpicker input,#label-colorpicker input,#node-strokeWidth,#node-width,#node-height').attr('disabled', '').val('');
        },
        createStepSelectOption: function () {
            if (fastflow.selectedNode != null) {
                if (fastflow.selectedNode.data['type'] == 'condition') {
                    let outNodes = fastflow.graph.getNeighbors(fastflow.selectedNode, options = {outgoing: true});
                    if (outNodes.length != 0) {
                        outNodes.forEach(function (outNode) {
                            $('.step-select:last').append('<option value="' + outNode.id + '">' + outNode.getAttrs().label.text + '</option>');
                        });
                    }

                }
            }
        },
        expandAttributeblank:function () {
             $('.xm-toolbar').css("right","516px");
             $('.workspace').css("right","516px");
             $('.attributeblank').css('visibility','visible');
        },
        collapseAttributeblank:function () {
            $('.attributeblank').css('visibility','hidden');
            $('.xm-toolbar').css("right","16px");
            $('.workspace').css("right","16px");
        },
    }
    return fastflow;
})


















